﻿
using System;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.IO;
using System.Linq;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Threading;
using Jade.Tools.SL.Windows.Extensions;
using JulMar.Silverlight.Interfaces;
using JulMar.Silverlight.Mvvm;
using JulMar.Siverlight.Helpers.Interactivity;
using MediaBrowserSL.RIA.MediaBrowserServiceReference;
using MediaBrowserSL.RIA.MvvmUtils;
using MediaBrowserSL.RIA.MvvmUtils.UI;
using MediaBrowserSL.RIA.Services;
using MediaBrowserSL.RIA.Tools;
using System.ServiceModel;

namespace MediaBrowserSL.RIA.ViewModels
{
    /// <summary>
    ///  Music View Model
    /// </summary>
    public class PageMusicViewModel : PageViewModelBase
    {
        #region Private member

        private IErrorVisualizer errorVisualizer;
        private MediaElement mediaElement;
        private string statusPlayer;
        private DispatcherTimer progressTimer;
        private string currentProgress;
        private MediaElementState CurrentState;
        private ICustomMessageBoxVisualizer customMessageBoxVisualizer;
        private IManageAlbumsVisualizer manageAlbumsVisualizer;
        private bool isDeleting;
        private bool isDroping;

        #endregion

        #region Public Properties

        public override string Name
        {
            get { return "Page Musics"; }
        }

        public string StatusPlayer
        {
            get
            {
                return this.statusPlayer;
            }
            set
            {
                this.statusPlayer = value;
                OnPropertyChanged("StatusPlayer");
            }
        }

        public double TotalDuration
        {
            get
            {
                if (mediaElement != null)
                {
                    if (mediaElement.NaturalDuration.HasTimeSpan)
                    {
                        return mediaElement.NaturalDuration.TimeSpan.TotalSeconds;
                    }
                    else
                    {
                        return 0;
                    }
                }
                else
                {
                    return 0;
                }
            }
        }

        public double CurrentPosition
        {
            get
            {
                if (mediaElement != null)
                {
                    return mediaElement.Position.TotalSeconds;
                }
                else
                {
                    return 0;
                }
            }
            set
            {
                mediaElement.Position = new TimeSpan(0, 0, (int)value);
                OnPropertyChanged("CurrentProgress");
            }
        }

        public string CurrentProgress
        {
            get
            {
                return this.currentProgress;
            }
            set
            {
                this.currentProgress = value;
                OnPropertyChanged("CurrentProgress");
            }
        }

        public bool IsDeleting
        {
            get
            {
                return isDeleting;
            }
            set
            {

                isDeleting = value;
                OnPropertyChanged("IsDeleting");
                RaiseCanExecuteChanged();
            }
        }

        public bool IsDroping
        {
            get
            {
                return isDroping;
            }
            set
            {

                isDroping = value;
                OnPropertyChanged("IsDroping");
                RaiseCanExecuteChanged();
            }
        }

        #endregion

        #region Comand

        public ICommand MediaOpenedCommand
        {
            get;
            private set;
        }

        public ICommand MediaFailedCommand
        {
            get;
            private set;
        }

        public DelegatingCommand PlayMusicCommand
        {
            get;
            private set;
        }

        public DelegatingCommand PauseMusicCommand
        {
            get;
            private set;
        }

        public DelegatingCommand StopMusicCommand
        {
            get;
            private set;
        }

        public ICommand PrepareAddAlbumCommand
        {
            get;
            private set;
        }

        public ICommand PrepareUpdateAlbumCommand
        {
            get;
            private set;
        }

        public DelegatingCommand DeleteAlbumCommand
        {
            get;
            private set;
        }

        public ICommand DropMusicCommand
        {
            get;
            private set;
        }

        public ICommand DeleteMusicCommand
        {
            get;
            private set;
        }

        #endregion

        public PageMusicViewModel(IMediaRiaServices service)
            : base(service)
        {
            errorVisualizer = Resolve<IErrorVisualizer>();
            customMessageBoxVisualizer = Resolve<ICustomMessageBoxVisualizer>();
            manageAlbumsVisualizer = Resolve<IManageAlbumsVisualizer>();

            MediaOpenedCommand = new DelegatingCommand<EventInformation>(MediaOpened);
            MediaFailedCommand = new DelegatingCommand<EventInformation>(MediaFailed);
            PlayMusicCommand = new DelegatingCommand(PlayMusic, CanPlayMusic);
            PauseMusicCommand = new DelegatingCommand(PauseMusic, CanPauseMusic);
            StopMusicCommand = new DelegatingCommand(StopMusic, CanStopMusic);

            PrepareAddAlbumCommand = new DelegatingCommand(PrepareAddAlbum);
            PrepareUpdateAlbumCommand = new DelegatingCommand(PrepareUpdateAlbum);
            DeleteAlbumCommand = new DelegatingCommand(DeleteAlbum);

            DropMusicCommand = new DelegatingCommand<EventInformation>(DropMusic);

            DeleteMusicCommand = new DelegatingCommand<EventInformation>(DeleteMusic);

            this.progressTimer = new DispatcherTimer();
            this.progressTimer.Interval = TimeSpan.FromSeconds(1);
            this.progressTimer.Tick += this.ProgressTimer_Tick;
            CurrentProgress = "00:00 / 00:00";
            CurrentState = MediaElementState.Stopped;
        }

        #region private Methods

        /// <summary>
        /// Return Medias
        /// </summary>
        /// <param name="movies"></param>
        private void GetListMediasByCategory(IEnumerable<Media> musics, Exception ex)
        {
            if (ex == null)
            {
                if (musics != null)
                {
                    if (medias != null) { medias.Clear(); } else { medias = new ObservableCollection<Media>(); }
                    foreach (var m in musics)
                    {
                        medias.Add(m);
                    }
                    sourceMediasView.Source = medias;
                    MediasView.MoveCurrentToFirst();
                    sourceMediasView.View.CurrentChanged += View_CurrentChanged;
                    OnPropertyChanged("MediasView");
                    View_CurrentChanged(null, null);
                }
            }
            else
            {
                if (customMessageBoxVisualizer != null)
                {
                    customMessageBoxVisualizer.Show(null, ((FaultException<ErrorDataContract>)ex).Detail.Detail, ex.Message, MessageBoxButton.OK, MessageBoxImage.Error);
                }
            }
        }

        void View_CurrentChanged(object sender, EventArgs e)
        {
            StopMusic();
            if (CurrentMedia != null)
            {
                mediaItems = new ObservableCollection<Media>(CurrentMedia.MediaItems);
                sourceMediaItemsView.Source = mediaItems;
                sourceMediaItemsView.View.CurrentChanged += mediaItemsView_CurrentChanged;
                OnPropertyChanged("CurrentMedia");
                OnPropertyChanged("MediaItemsView");
                mediaItemsView_CurrentChanged(null, null);
                RaiseCanExecuteChanged();
            }
        }

        void mediaItemsView_CurrentChanged(object sender, EventArgs e)
        {
            OnPropertyChanged("CurrentMediaItem");
            StatusPlayer = String.Empty;
        }

        private void RaiseCanExecuteChanged()
        {
            if (PlayMusicCommand != null)
            {
                PlayMusicCommand.RaiseCanExecuteChanged();
                PauseMusicCommand.RaiseCanExecuteChanged();
                StopMusicCommand.RaiseCanExecuteChanged();
            }
        }

        #region Add/Update Album

        /// <summary>
        /// Prepare Add Album
        /// </summary>
        private void PrepareAddAlbum()
        {
            if (manageAlbumsVisualizer != null) manageAlbumsVisualizer.Show();
            SendMessage(MediatorMessages.EditAlbum, new Media());
        }

        /// <summary>
        /// Prepare Update Album
        /// </summary>
        private void PrepareUpdateAlbum()
        {
            if (CurrentMedia != null)
            {
                if (manageAlbumsVisualizer != null) manageAlbumsVisualizer.Show();
                SendMessage(MediatorMessages.EditAlbum, CurrentMedia);
            }
        }

        #endregion

        #region Delete Album

        /// <summary>
        /// Delete Album
        /// </summary>
        private void DeleteAlbum()
        {
            if (CurrentMedia != null && !IsDeleting)
            {
                if ((mediaItems == null) || (mediaItems.Count == 0))
                {
                    if (customMessageBoxVisualizer != null)
                    {
                        customMessageBoxVisualizer.Show(ConfirmDeleteAlbum, "Etes-vous sur de vouloir supprimer cet Album ?", "Supprimer", MessageBoxButton.OKCancel, MessageBoxImage.Question);
                    }
                    else
                    {
                        IsDeleting = true;
                        service.DeleteMedia(MediaDeleted, CurrentMedia, SessionMb.CurrentUser);
                    }
                }
                else
                {
                    if (customMessageBoxVisualizer != null)
                    {
                        customMessageBoxVisualizer.Show(null, "Vous devez d'abord supprimer toutes les musiques liées à cet album !", "Supprimer", MessageBoxButton.OK, MessageBoxImage.Error);
                    }
                }
            }
        }

        /// <summary>
        /// Confirm Delete Album
        /// </summary>
        /// <param name="r"></param>
        private void ConfirmDeleteAlbum(MessageBoxResult r)
        {
            if (r == MessageBoxResult.OK)
            {
                IsDeleting = true;
                service.DeleteMedia(MediaDeleted, CurrentMedia, SessionMb.CurrentUser);
            }
        }

        /// <summary>
        /// Media Deleted
        /// </summary>
        /// <param name="e"></param>
        private void MediaDeleted(Exception ex)
        {
            IsDeleting = false;
            if (ex == null)
            {
                if (medias != null) { medias.Remove(CurrentMedia); }
            }
            else
            {
                if (customMessageBoxVisualizer != null)
                {
                    customMessageBoxVisualizer.Show(null, ((FaultException<ErrorDataContract>)ex).Detail.Detail, ex.Message, MessageBoxButton.OK, MessageBoxImage.Error);
                }
            }
        }

        #endregion

        #region Delete Music

        /// <summary>
        /// Delete Music
        /// </summary>
        /// <param name="e"></param>
        private void DeleteMusic(EventInformation e)
        {
            KeyEventArgs ea = e.EventParameter as KeyEventArgs;

            if (ea.Key == Key.Delete)
            {

                if (customMessageBoxVisualizer != null)
                {
                    customMessageBoxVisualizer.Show(ConfirmDeleteMusic, "Etes-vous sur de vouloir supprimer cette musique ?", "Supprimer", MessageBoxButton.OKCancel, MessageBoxImage.Question);
                }
                else
                {
                    service.DeleteMedia(MusicDeleted, CurrentMediaItem, SessionMb.CurrentUser);
                }
            }
        }

        /// <summary>
        /// Confimr Delete Music
        /// </summary>
        /// <param name="r"></param>
        private void ConfirmDeleteMusic(MessageBoxResult r)
        {
            if (r == MessageBoxResult.OK)
            {
                service.DeleteMedia(MusicDeleted, CurrentMediaItem, SessionMb.CurrentUser);
            }
        }

        /// <summary>
        /// Music Deleted
        /// </summary>
        /// <param name="e"></param>
        private void MusicDeleted(Exception ex)
        {
            if (ex == null)
            {
                if (CurrentMedia != null) { CurrentMedia.MediaItems.Remove(CurrentMediaItem); }
                if (mediaItems != null) { mediaItems.Remove(CurrentMediaItem); }
            }
            else
            {
                if (customMessageBoxVisualizer != null)
                {
                    customMessageBoxVisualizer.Show(null, ((FaultException<ErrorDataContract>)ex).Detail.Detail, ex.Message, MessageBoxButton.OK, MessageBoxImage.Error);
                }
            }
        }

        #endregion

        #region Drop/Create Music

        /// <summary>
        /// Drop Music
        /// </summary>
        /// <param name="e"></param>
        private void DropMusic(EventInformation e)
        {
            if (CurrentMedia != null)
            {
                DragEventArgs de = e.EventParameter as DragEventArgs;

                if ((de.Data != null) && (de.Data.GetDataPresent(DataFormats.FileDrop)))
                {
                    FileInfo[] files = de.Data.GetData(DataFormats.FileDrop) as FileInfo[];

                    if (files != null)
                    {
                        FileInfo f = files[0];
                        if (f.Name.IsMusicFile())
                        {
                            Media mediaItem = new Media() { Name = Path.GetFileNameWithoutExtension(f.Name), Description = f.Name, UrlContent = f.Name, CreationDate = DateTime.Now };
                            mediaItem.Category = new Category() { Id = 2 };
                            IsDroping = true;
                            service.CreateMediaItem(MediaItemCreated, mediaItem, CurrentMedia, SessionMb.CurrentUser, null, f);
                        }
                    }
                }
            }
        }

        /// <summary>
        /// Media Item Created
        /// </summary>
        /// <param name="m"></param>
        /// <param name="ex"></param>
        private void MediaItemCreated(Media m, Exception ex)
        {
            IsDroping = false;
            if (ex == null)
            {
                CurrentMedia.MediaItems.Add(m);
                mediaItems.Add(m);
            }
            else if (ex.GetType().Equals(typeof(FullServerException)))
            {
                if (customMessageBoxVisualizer != null)
                {
                    customMessageBoxVisualizer.Show(null,
                                                        "Votre espace serveur est plein !",
                                                        "Espace indisponible",
                                                        MessageBoxButton.OK,
                                                        MessageBoxImage.Error);
                }

            }
            else
            {
                if (customMessageBoxVisualizer != null)
                {
                    customMessageBoxVisualizer.Show(null, ((FaultException<ErrorDataContract>)ex).Detail.Detail, ex.Message, MessageBoxButton.OK, MessageBoxImage.Error);
                }
            }
        }

        #endregion

        #endregion

        #region Public Methods

        /// <summary>
        /// Update Current User
        /// </summary>
        /// <param name="page"></param>
        [MessageMediatorTarget(MediatorMessages.UpdateCurrentUser)]
        public void UpdateCurrentUser(User user)
        {
            service.GetListMediasByCategory(GetListMediasByCategory, SessionMb.CurrentUser.Id, 2);
        }

        /// <summary>
        /// LogOut
        /// </summary>
        [MessageMediatorTarget(MediatorMessages.LogOut)]
        public void LogOut(User user)
        {
            StopMusic();
            if (medias != null)
            {
                if (sourceMediaItemsView.Source != null)
                {
                    (sourceMediaItemsView.Source as ObservableCollection<Media>).Clear();
                }
                medias.Clear();
            }
            else
            {
                medias = new ObservableCollection<Media>();
            }
        }

        /// <summary>
        /// Add Album to List
        /// </summary>
        /// <param name="page"></param>
        [MessageMediatorTarget(MediatorMessages.AddAlbumToList)]
        public void AddAlbumToList(Media m)
        {
            if (medias != null)
            {
                m.MediaItems = new ObservableCollection<Media>();
                medias.Add(m);
            }
            MediasView.MoveCurrentToLast();
        }

        /// <summary>
        /// Update Album to List
        /// </summary>
        /// <param name="page"></param>
        [MessageMediatorTarget(MediatorMessages.UpdateAlbumToList)]
        public void UpdateAlbumToList(Media m)
        {
            var movie = (from mo in Medias where m.Id == mo.Id select mo).SingleOrDefault();
            movie.Name = m.Name;
            movie.Description = m.Description;
        }

        #endregion

        #region Method Control Music

        /// <summary>
        /// Play Music
        /// </summary>
        private void PlayMusic()
        {
            mediaElement.Play();
            progressTimer.Start();
            CurrentState = MediaElementState.Playing;
            RaiseCanExecuteChanged();
        }

        /// <summary>
        /// Can Play
        /// </summary>
        /// <returns></returns>
        private bool CanPlayMusic()
        {
            bool CanPlay = false;
            if ((mediaItems != null) && (mediaItems.Count > 0))
            {
                if (mediaElement != null)
                {
                    if (CurrentState != MediaElementState.Playing)
                    {
                        CanPlay = true;
                    }
                }
            }
            return CanPlay;
        }

        /// <summary>
        /// Pause Music
        /// </summary>
        private void PauseMusic()
        {
            if (CurrentState == MediaElementState.Playing)
            {
                if (mediaElement.CanPause)
                {
                    mediaElement.Pause();
                }
                else
                {
                    mediaElement.Stop();
                }
                progressTimer.Stop();
                CurrentState = MediaElementState.Paused;
            }
            else
            {
                mediaElement.Play();
                progressTimer.Start();
                CurrentState = MediaElementState.Playing;
            }
            RaiseCanExecuteChanged();
        }

        /// <summary>
        /// can pause
        /// </summary>
        /// <returns></returns>
        private bool CanPauseMusic()
        {
            bool CanPause = false;

            if ((mediaItems != null) && (mediaItems.Count > 0))
            {
                if (mediaElement != null)
                {
                    if (CurrentState == MediaElementState.Playing)
                    {
                        CanPause = true;
                    }
                }
            }

            return CanPause;
        }

        /// <summary>
        /// Stop Music
        /// </summary>
        private void StopMusic()
        {
            if (mediaElement != null)
            {
                progressTimer.Stop();
                mediaElement.Stop();
                CurrentProgress = "00:00 / 00:00";
                mediaElement.Position = new TimeSpan(0, 0, 0);
                OnPropertyChanged("CurrentPosition");
                CurrentState = MediaElementState.Stopped;
            }
            RaiseCanExecuteChanged();
        }

        /// <summary>
        /// can stop
        /// </summary>
        /// <returns></returns>
        private bool CanStopMusic()
        {
            bool CanStop = false;

            if ((mediaItems != null) && (mediaItems.Count > 0))
            {
                if (mediaElement != null)
                {
                    CanStop = true;
                }
            }

            return CanStop;
        }

        /// <summary>
        /// Opened Media
        /// </summary>
        /// <param name="param"></param>
        public void MediaOpened(EventInformation e)
        {
            MediaElement parmMediaElement = (MediaElement)e.CommandArgument;
            mediaElement = parmMediaElement;
            OnPropertyChanged("TotalDuration");
            StatusPlayer = String.Empty;
            if (CurrentState == MediaElementState.Playing)
            {
                PlayMusic();
            }
            else
            {
                CurrentState = MediaElementState.Stopped;
            }
            RaiseCanExecuteChanged();
        }

        /// <summary>
        /// Media Failed
        /// </summary>
        /// <param name="e"></param>
        public void MediaFailed(EventInformation e)
        {
            if (String.IsNullOrEmpty(CurrentMediaItem.UrlContent))
            {
                StatusPlayer = "Pas de fichier pour ce média !";
            }
            else
            {
                ExceptionRoutedEventArgs ex = e.EventParameter as ExceptionRoutedEventArgs;
                StatusPlayer = ex.ErrorException.Message;
            }
            RaiseCanExecuteChanged();
        }

        /// <summary>
        /// Progreess Media
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void ProgressTimer_Tick(object sender, EventArgs e)
        {
            if (mediaElement.NaturalDuration != Duration.Automatic)
            {
                CurrentProgress = string.Format(
                   "{0}:{1} / {2}:{3}",
                   Math.Floor(mediaElement.Position.TotalMinutes).ToString("00"),
                   mediaElement.Position.Seconds.ToString("00"),
                   Math.Floor(mediaElement.NaturalDuration.TimeSpan.TotalMinutes).ToString("00"),
                   mediaElement.NaturalDuration.TimeSpan.Seconds.ToString("00"));

                OnPropertyChanged("CurrentPosition");
            }
        }

        #endregion

    }
}
